#ifndef _GWBASE_BASE_STATUS_H_
#define _GWBASE_BASE_STATUS_H_

#include <assert.h>
#include <errno.h>
#include <string>
#include <ostream>

// Status is used to return result with more information than
// a single error code.

namespace dicom {

class Status {
 public:
  enum Code {
    kOk = 0,
    kIOError,
    kNetworkError,
    kOther
  };

  Status() : code_(kOk), subcode_(0) {}
  Status(Code code, const std::string& msg)
      : code_(code), subcode_(0), msg_(msg) {}

  Status(Code code, const std::string& msg1, const std::string& msg2)
      : code_(code), subcode_(0), msg_(msg1 + ": " + msg2) {}

  Status(Code code, int subcode, const std::string& msg)
      : code_(code), subcode_(subcode), msg_(msg) {}

  Status(Code code, int subcode, const std::string& msg1,
         const std::string& msg2)
      : code_(code), subcode_(subcode), msg_(msg1 + ": " + msg2) {}

  bool ok() const { return code_ == kOk; }

  Code code() const { return code_; }
  int subcode() const { return subcode_; }
  const std::string& msg() const { return msg_; }

  std::string ToString() const;

 private:
  Code code_;
  int subcode_;
  std::string msg_;
};

Status IOError(const std::string& context, int err_no);
Status NetworkError(const std::string& context, int socket_err_no);

inline std::ostream& operator<<(std::ostream& os, const Status& s) {
  os << s.ToString();
  return os;
}
}

#endif  // _GWBASE_BASE_STATUS_H_
